package com.byedu.util.yunpian.util;

/**
 * Created by bingone on 15/11/18.
 */
import org.apache.commons.codec.binary.Base64;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Random;

/**
 * Tea绠楁硶
 * 姣忔鎿嶄綔鍙互澶勭悊8涓瓧鑺傛暟鎹�
 * KEY涓�16瀛楄妭,搴斾负鍖呭惈4涓猧nt鍨嬫暟鐨刬nt[]锛屼竴涓猧nt涓�4涓瓧鑺�
 * 鍔犲瘑瑙ｅ瘑杞暟搴斾负8鐨勫�嶆暟锛屾帹鑽愬姞瀵嗚疆鏁颁负64杞�
 * */
public class TeaUtil {
    //鍔犲瘑
    public static byte[] encrypt(byte[] content, int offset, int[] key, int times){//times涓哄姞瀵嗚疆鏁�
        int[] tempInt = byteToInt(content, offset);
        int y = tempInt[0], z = tempInt[1], sum = 0, i;
        int delta=0x9e3779b9; //杩欐槸绠楁硶鏍囧噯缁欑殑鍊�
        int a = key[0], b = key[1], c = key[2], d = key[3];

        for (i = 0; i < times; i++) {
            sum += delta;
            y += ((z<<4) + a) ^ (z + sum) ^ ((z>>5) + b);
            z += ((y<<4) + c) ^ (y + sum) ^ ((y>>5) + d);
        }
        tempInt[0]=y;
        tempInt[1]=z;
        return intToByte(tempInt, 0);
    }

    //瑙ｅ瘑
    public static byte[] decrypt(byte[] encryptContent, int offset, int[] key, int times){
        int[] tempInt = byteToInt(encryptContent, offset);
        int y = tempInt[0], z = tempInt[1], sum = 0xC6EF3720, i;
        int delta=0x9e3779b9; //杩欐槸绠楁硶鏍囧噯缁欑殑鍊�
        int a = key[0], b = key[1], c = key[2], d = key[3];

        for(i = 0; i < times; i++) {
            z -= ((y<<4) + c) ^ (y + sum) ^ ((y>>5) + d);
            y -= ((z<<4) + a) ^ (z + sum) ^ ((z>>5) + b);
            sum -= delta;
        }
        tempInt[0] = y;
        tempInt[1] = z;

        return intToByte(tempInt, 0);
    }

    //byte[]鍨嬫暟鎹浆鎴恑nt[]鍨嬫暟鎹�
    private static int[] byteToInt(byte[] content, int offset){

        int[] result = new int[content.length >> 2]; //闄や互2鐨刵娆℃柟 == 鍙崇Щn浣� 鍗� content.length / 4 == content.length >> 2
        for(int i = 0, j = offset; j < content.length; i++, j += 4){
            result[i] = transform(content[j + 3]) | transform(content[j + 2]) << 8 |
                transform(content[j + 1]) << 16 | (int)content[j] << 24;
        }
        return result;

    }

    //int[]鍨嬫暟鎹浆鎴恇yte[]鍨嬫暟鎹�
    private static byte[] intToByte(int[] content, int offset){
        byte[] result = new byte[content.length << 2]; //涔樹互2鐨刵娆℃柟 == 宸︾Щn浣� 鍗� content.length * 4 == content.length << 2
        for(int i = 0, j = offset; j < result.length; i++, j += 4){
            result[j + 3] = (byte)(content[i] & 0xff);
            result[j + 2] = (byte)((content[i] >> 8) & 0xff);
            result[j + 1] = (byte)((content[i] >> 16) & 0xff);
            result[j] = (byte)((content[i] >> 24) & 0xff);
        }
        return result;
    }

    //鑻ユ煇瀛楄妭琚В閲婃垚璐熺殑鍒欓渶灏嗗叾杞垚鏃犵鍙锋鏁�
    private static int transform(byte temp){
        int tempInt = (int)temp;
        if(tempInt < 0){
            tempInt += 256;
        }
        return tempInt;
    }


    /**
     * 閫氳繃TEA绠楁硶鍔犲瘑淇℃伅
     * @param info
     * @param key
     * @return
     */
    public static byte[] encryptByTea(String info, int[] key) throws UnsupportedEncodingException {
        byte[] temp = info.getBytes("UTF-8");
        int n = 8 - temp.length % 8;//鑻emp鐨勪綅鏁颁笉瓒�8鐨勫�嶆暟,闇�瑕佸～鍏呯殑浣嶆暟
        byte[] encryptStr = new byte[temp.length + n];
        encryptStr[0] = (byte)n;
        System.arraycopy(temp, 0, encryptStr, n, temp.length);
        byte[] result = new byte[encryptStr.length];
        for(int offset = 0; offset < result.length; offset += 8){
            byte[] tempEncrpt = TeaUtil.encrypt(encryptStr, offset, key, 32);
            System.arraycopy(tempEncrpt, 0, result, offset, 8);
        }
        return result;
    }


    public static String encryptForYunpianV2(String info, String secret)
        throws UnsupportedEncodingException {
        if(StringUtil.isNullOrEmpty(secret))
            return info;
        int[] key = getKeyByApikey(getApiSecret(secret));
        byte[] bytes = encryptByTea(info, key);
        Base64 base64 = new Base64();
        return base64.encodeAsString(bytes);
    }
    public static String getApiSecret(String secret){
        return secret+secret+secret+secret;
    }
    public static String decryptForYunpianV2(String msg, String secret)
        throws IOException {
        int[] key = getKeyByApikey(secret + secret + secret + secret);
        //        byte[] secretInfo = Base64.decodeBase64(secret);
        Base64 base64 = new Base64();
        byte[] secretInfo = base64.decode(msg);
        return decryptByTea(secretInfo, key);
    }
    /**
     * 閫氳繃TEA绠楁硶瑙ｅ瘑淇℃伅
     * @param secretInfo
     * @param KEY
     * @return
     */
    public static String decryptByTea(byte[] secretInfo, int[] KEY)
        throws UnsupportedEncodingException {
        byte[] decryptStr = null;
        byte[] tempDecrypt = new byte[secretInfo.length];
        for (int offset = 0; offset < secretInfo.length; offset += 8) {
            decryptStr = TeaUtil.decrypt(secretInfo, offset, KEY, 32);
            System.arraycopy(decryptStr, 0, tempDecrypt, offset, 8);
        }

        int n = tempDecrypt[0];
        return new String(tempDecrypt, n, decryptStr.length - n, "UTF-8");
    }

    private static byte[] stringToByte(String str){
        String[] list = str.split(",");
        byte[] b = new byte[list.length];
        for (int i = 0; i < list.length; i++) {
            b[i] = Byte.parseByte(list[i]);
        }
        return b;
    }

    public static int[] getKeyByApikey(String apikey){
        int[] key = new int[4];
        key[0] = Integer.parseInt(apikey.substring(0, 7), 16);
        key[1] = Integer.parseInt(apikey.substring(8, 15), 16);
        key[2] = Integer.parseInt(apikey.substring(16, 23), 16);
        key[3] = Integer.parseInt(apikey.substring(24, 31), 16);
        return key;
    }
 
}
